﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace JsVersionMaker
{
	public partial class Form1 : Form
	{
		private MD5 md5 = MD5.Create();
		private Dictionary<string, string> cache = new Dictionary<string, string>();

		public Form1()
		{
			InitializeComponent();
		}

		private void buttonSelect_Click(object sender, EventArgs e)
		{
			using (var fbd = new FolderBrowserDialog())
			{
				DialogResult result = fbd.ShowDialog();

				if (result == DialogResult.OK && !string.IsNullOrWhiteSpace(fbd.SelectedPath))
				{
					textBoxDir.Text = fbd.SelectedPath;
				}
			}
		}

		private void buttonStart_Click(object sender, EventArgs e)
		{
			cache.Clear();
			if (string.IsNullOrWhiteSpace(textBoxDir.Text) == false)
			{
				log("start");
				DirSearch(textBoxDir.Text);
				log("end");
				MessageBox.Show("处理结束");
			}
		}

		private void DirSearch(string sDir)
		{
			try
			{
				foreach (string f in Directory.GetFiles(sDir))
				{
					if (f.ToLower().EndsWith("html"))
					{
						FixFile(f);
					}
				}
				foreach (string d in Directory.GetDirectories(sDir))
				{
					DirSearch(d);
				}
			}
			catch (System.Exception excpt)
			{
				MessageBox.Show(excpt.Message);
			}
		}

		private void FixFile(string sFile)
		{
			log("deal " + sFile);
			string dir = sFile.Substring(0, sFile.LastIndexOf("\\") + 1);

			string text = File.ReadAllText(sFile);
			string text2 = text;
			bool modify = false;
			Match m;
			string HRefPattern = @"(src|href)\s*=\s*(?:[""'](?<1>[^""']*)[""']|(?<1>\S+))";

			try
			{
				m = Regex.Match(text, HRefPattern, RegexOptions.IgnoreCase | RegexOptions.Compiled, TimeSpan.FromSeconds(5));
				while (m.Success)
				{
					try
					{
						string url = m.Groups[1].ToString();
						if (url.ToLower().StartsWith("http") == false && url.ToLower().StartsWith("//") == false)
						{
							int jsPos = url.IndexOf(".js");
							int cssPos = url.IndexOf(".css");
							if (jsPos > 0 || cssPos > 0)
							{
								//log("Found " + url);
								string file = url.Substring(0, Math.Max(jsPos + 3, cssPos + 4)).Replace("/", "\\");
								string md5str;
								if (cache.ContainsKey(dir + file))
								{
									md5str = cache[dir + file];
								}
								else
								{
									md5str = GetFileMD5(dir + file);
									cache.Add(dir + file, md5str);
								}

								//log("file: " + file + "  md5:" + md5str);
								file = file.Replace("\\", "/") + "?_=" + md5str;
								if (url.Equals(file) == false)
								{
									log("file:" + file);
									text2 = text2.Replace(url, file);
									modify = true;
								}
							}
						}
					}
					catch (Exception e)
					{
						//log("err:" + e);
					}
					m = m.NextMatch();
				}
			}
			catch (RegexMatchTimeoutException)
			{
				Console.WriteLine("The matching operation timed out.");
			}

			if (modify == true)
			{
				File.WriteAllText(sFile, text2);
			}
		}

		private string GetFileMD5(string file)
		{
			using (var stream = File.OpenRead(file))
			{
				var hash = md5.ComputeHash(stream);
				return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
			}
		}

		private void log(string txt)
		{
			textBoxLog.AppendText(txt + Environment.NewLine);
		}
	}
}
